<template>
  <div
    class="drag-container column"
    @mousedown="startDrag"
    @mouseup="endDrag"
    @mousemove.prevent="onMouseMove"
  >
    <div v-for="(item, index) in checkboxList" :key="index">
      <input type="checkbox" :value="item.value" v-model="selectedItems">
      <span>{{ item?.label }}</span>
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue';

// 模拟复选框列表数据，实际应用中可替换为真实数据来源
const checkboxList = ref([
  { label: '选项1', value: 'option1' },
  { label: '选项2', value: 'option2' },
  { label: '选项3', value: 'option3' },
  { label: '选项4', value: 'option4' },
  { label: '选项5', value: 'option5' },
]);

// 用于存储已选中的复选框的值
const selectedItems = ref([]);

// 记录初始点击（拖拽开始）时的位置坐标
let startX;
let startY;
// 记录鼠标抬起（拖拽结束）时的位置坐标
let endX;
let endY;
// 标记是否正在拖拽
let isDragging = false;

// 开始拖拽，记录起始位置坐标，并设置正在拖拽标志为true
const startDrag = (e) => {
  console.log(`开始拖拽 ing👇`);
  startX = e.clientX;
  startY = e.clientY;
  isDragging = true;
};

// 结束拖拽，记录结束位置坐标，并设置正在拖拽标志为false，同时调用处理拖拽结束后的复选框选中逻辑
const endDrag = (e) => {
  console.log(`结束拖拽 ing👇`);
  endX = e.clientX;
  endY = e.clientY;
  isDragging = false;
  handleDragEnd();
};

// 鼠标移动时，先判断是否处于拖拽状态，若是则更新当前鼠标位置坐标（仅用于记录拖拽轨迹，此处暂不做其他逻辑）
const onMouseMove = (e) => {
  if (isDragging) {
    // 这里可以根据需求添加更多逻辑，比如实时显示拖拽区域的可视化提示等，目前暂只用于记录拖拽状态下的鼠标位置
  }
};

// 处理拖拽结束后的复选框选中逻辑，根据初始位置和结束位置判断复选框是否在范围内并进行相应选中/取消选中操作
const handleDragEnd = () => {
  if (!isDragging) {
    return;
  }
  const elements = document.querySelectorAll('.drag-container input[type="checkbox"],.drag-container span');
  for (const element of elements) {
    const rect = element.getBoundingClientRect();
    const isInRangeX = (startX <= endX
     ? rect.left >= startX && rect.right <= endX
      : rect.left <= startX && rect.right >= endX)
      || (startX <= endX
       ? rect.right >= startX && rect.left <= endX
        : rect.right <= startX && rect.left >= endX);
    const isInRangeY = (startY <= endY
     ? rect.top >= startY && rect.bottom <= endY
      : rect.top <= startY && rect.bottom >= endY)
      || (startY <= endY
       ? rect.bottom >= startY && rect.top <= endY
        : rect.bottom <= startY && rect.top >= endY);
    const index = checkboxList.value.findIndex((item) => {
      if (element.tagName === 'INPUT') {
        return item.value === element.value;
      } else if (element.tagName === 'SPAN') {
        return item.label === element.textContent;
      }
      return false;
    });
    if (index > -1) {
      if (isInRangeX && isInRangeY) {
        // 如果复选框在初始位置和结束位置构成的矩形区域内，则选中
        if (!selectedItems.value.includes(checkboxList.value[index].value)) {
          selectedItems.value.push(checkboxList.value[index].value);
        }
      } else {
        // 如果不在该区域内，则取消选中（如果之前已选中的话）
        const selectedIndex = selectedItems.value.indexOf(checkboxList.value[index].value);
        if (selectedIndex > -1) {
          selectedItems.value.splice(selectedIndex, 1);
        }
      }
    }
  }
};
</script>

<style scoped>
.drag-container {
  border: 1px solid #ccc;
  padding: 10px;
  margin-bottom: 10px;
  user-select: none;
}
.drag-container span {
  user-select: none;
}
</style>